package com.franklin.ideaplugin.maphelper.resolver.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.franklin.ideaplugin.api.beans.declaration.IDeclaration;
import com.franklin.ideaplugin.api.beans.variable.IVariable;
import com.franklin.ideaplugin.maphelper.beans.colmember.IColMember;
import com.franklin.ideaplugin.maphelper.col.declaration.IColDeclaration;
import com.franklin.ideaplugin.maphelper.resolver.IColMemberResolver;
import com.franklin.ideaplugin.maphelper.utils.PsiColUtils;
import com.google.common.collect.Sets;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * new表达
 *
 * @author Ye Junhui
 * @since 2024/3/5
 */
public abstract class AbstractNewExpressionColMemberResolver implements IColMemberResolver {

    @Override
    public boolean supports(IColDeclaration colDeclaration) {
        IDeclaration declaration = colDeclaration.getDeclaration();
        PsiNewExpression psiNewExpression = declaration.getCreateExpression(PsiNewExpression.class);
        return Objects.nonNull(psiNewExpression);
    }

    @Override
    public Collection<IColMember> resolveColMembers(PsiElement psiExpression, IColDeclaration colDeclaration) {
        //结果
        Set<IColMember> result = Sets.newLinkedHashSet();
        //本地变量
        IDeclaration declaration = colDeclaration.getDeclaration();
        IVariable variable = declaration.getVariable();
        if (Objects.isNull(variable)) {
            return result;
        }

        //构造器内
        PsiNewExpression psiNewExpression = declaration.getCreateExpression(PsiNewExpression.class);
        processConstructorMembers(result, psiNewExpression);

        //代码块
        List<PsiCodeBlock> psiCodeBlockList = PsiTreeUtil.collectParents(psiExpression, PsiCodeBlock.class, false, psiElement -> false);
        //由内往外寻找代码块
        psiCodeBlockList.forEach(psiCodeBlock -> {
            List<IColMember> psiColMemberInCodeBlock = findMemberInCodeBlock(variable, psiCodeBlock);
            CollectionUtil.addAll(result, psiColMemberInCodeBlock);
        });

        return result;
    }

    /**
     * 寻找成员变量
     *
     * @param variable
     * @param psiCodeBlock
     * @return
     */
    protected abstract List<IColMember> findMemberInCodeBlock(IVariable variable, @Nullable PsiCodeBlock psiCodeBlock);

    /**
     * 处理构造器中的成员
     *
     * @param resultSet
     * @param psiNewExpression
     */
    private void processConstructorMembers(Set<IColMember> resultSet, PsiNewExpression psiNewExpression) {
        Optional.ofNullable(PsiTreeUtil.getChildOfType(psiNewExpression, PsiExpressionList.class))
                .map(psiExpressionList -> PsiTreeUtil.getChildOfType(psiExpressionList, PsiExpression.class))
                .ifPresent(constructorExpression -> {
                    //定义
                    IColDeclaration colExpressionDeclaration = PsiColUtils.findColExpressionDeclaration(constructorExpression);
                    Collection<IColMember> constructorMembers = getColMemberResolverFactory()
                            .resolveExpression(constructorExpression, colExpressionDeclaration);
                    CollectionUtil.addAll(resultSet, constructorMembers);
                });
    }
}
